package com.qys.livesMall.shortVideo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import com.qys.livesMall.anchor.controller.LiveStreamUtils;
import com.qys.livesMall.anchor.model.entity.AnchorLivesRoom;
import com.qys.livesMall.anchor.model.entity.AnchorLivesSession;
import com.qys.livesMall.anchor.service.AnchorLivesRoomService;
import com.qys.livesMall.anchor.service.AnchorLivesSessionService;
import com.qys.livesMall.app.user.mapper.AppUserLevelMapper;
import com.qys.livesMall.app.user.mapper.H2AppUserMapper;
import com.qys.livesMall.app.user.model.dto.AppBaseDTO;
import com.qys.livesMall.app.user.model.entity.AppUserConcern;
import com.qys.livesMall.app.user.model.entity.AppUserLevel;
import com.qys.livesMall.app.user.model.entity.H2AppUser;
import com.qys.livesMall.app.user.service.AppUserConcernService;
import com.qys.livesMall.cache.RedisCache;
import com.qys.livesMall.common.exception.QysException;
import com.qys.livesMall.common.utils.MessageUtils;
import com.qys.livesMall.file.server.upload.model.entity.VideoStore;
import com.qys.livesMall.file.server.upload.service.VideoStoreService;
import com.qys.livesMall.framework.utils.SecurityUtils;
import com.qys.livesMall.framework.view.BaseQuery;
import com.qys.livesMall.shop.mapper.H2ShopBaseMapper;
import com.qys.livesMall.shop.mapper.ShopGoodsInfoMapper;
import com.qys.livesMall.shop.modal.entity.ShopGoodsInfo;
import com.qys.livesMall.shortVideo.constants.CacheConstants;
import com.qys.livesMall.shortVideo.event.ShortVideoAddEvent;
import com.qys.livesMall.shortVideo.mapper.H2ShortVideoMapper;
import com.qys.livesMall.shortVideo.mapper.H2ShortVideoTagMapper;
import com.qys.livesMall.shortVideo.mapper.ShortVideoGoodsInfoMapper;
import com.qys.livesMall.shortVideo.model.dto.ShortVideoEventDTO;
import com.qys.livesMall.shortVideo.model.dto.app.AppShortVideoPageDTO;
import com.qys.livesMall.shortVideo.model.dto.app.AppShortVideoSaveDTO;
import com.qys.livesMall.shortVideo.model.dto.sys.SysShortVideoQueryDTO;
import com.qys.livesMall.shortVideo.model.dto.sys.SysShortVideoSaveDTO;
import com.qys.livesMall.shortVideo.model.entity.*;
import com.qys.livesMall.shortVideo.model.enums.ShortVideoEventTypeEnum;
import com.qys.livesMall.shortVideo.model.vo.app.*;
import com.qys.livesMall.shortVideo.model.vo.sys.SysShortVideoVO;
import com.qys.livesMall.shortVideo.service.*;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;


/**
 * <p>
 * 短视频信息 服务实现类
 * </p>
 *
 * @author dp
 * @since 2023-05-04
 */
@Service
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class H2ShortVideoServiceImpl extends ServiceImpl<H2ShortVideoMapper, H2ShortVideo> implements IH2ShortVideoService {

    private final H2AppUserMapper appUserMapper;
    private final StringRedisTemplate redisTemplate;
    private final RedisCache redisCache;
    private final ApplicationContext applicationContext;
    private final IH2ShortVideoCategoryService videoCategoryService;
    private final ShortVideoUserService shortVideoUserService;
    private final ShortVideoHistoryService videoHistoryService;
    private final VideoStoreService videoStoreService;
    private final AppUserConcernService userConcernService;
    private final IH2ShortVideoCommentsService videoCommentsService;
    private final H2ShortVideoTagMapper h2ShortVideoTagMapper;
    private final H2ShortVideoMapper h2ShortVideoMapper;
    private final AnchorLivesRoomService anchorLivesRoomService;
    private final AppUserLevelMapper appUserLevelMapper;
    private final H2ShopBaseMapper shopBaseMapper;
    private final ShortVideoGoodsInfoMapper shortVideoGoodsInfoMapper;
    private final ShopGoodsInfoMapper shopGoodsInfoMapper;
    private final AnchorLivesSessionService anchorLivesSessionService;
    @Override
    public Page<SysShortVideoVO> pageBySystem(SysShortVideoQueryDTO queryDTO) {
        Page<SysShortVideoVO> voPage = baseMapper.pageBySystem(new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()), queryDTO);

        List<SysShortVideoVO> records = voPage.getRecords();
        Map<String,String> categoryMap =videoCategoryService.list().stream().collect(Collectors.toMap(H2ShortVideoCategory::getId,H2ShortVideoCategory::getName));
        records.forEach(e->{
            LambdaQueryWrapper<H2ShortVideoTag> wq = new LambdaQueryWrapper<>();
            wq.eq(H2ShortVideoTag::getVideoId, Long.valueOf(e.getId()));
            List<H2ShortVideoTag> tags= h2ShortVideoTagMapper.selectList(wq);
            if (tags==null){
                return;
            }
            List<String> categoryNames=new ArrayList<>();
            tags.stream().forEach(o->{
                categoryNames.add(categoryMap.get(String.valueOf(o.getTagCode())));
            });
            e.setShortVideoCategoryName(categoryNames);
        });

        return voPage.setRecords(records);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveVideoBySystem(SysShortVideoSaveDTO videoSaveDTO) {
        log.info("管理员操作短视频信息: {},--->{}", SecurityUtils.getUsername(), videoSaveDTO);

        H2ShortVideo shortVideo = new H2ShortVideo();
        BeanUtils.copyProperties(videoSaveDTO, shortVideo);
        shortVideo.setStatus(1);

        //用户信息
        H2AppUser h2AppUser = appUserMapper.selectById(videoSaveDTO.getUserId());
        if (null == h2AppUser) {
            throw new QysException(MessageUtils.message("user.null"));
        }
        shortVideo.setAvatar(h2AppUser.getAvatar());
        shortVideo.setUserName(h2AppUser.getNickName());

        if (StringUtils.isBlank(videoSaveDTO.getId())) {
            shortVideo.setCreateTime(LocalDateTime.now());
            shortVideo.setDeleted(false);
        }

        //封面图片
        shortVideo.setImg(getImg(shortVideo.getUrl()));

        saveOrUpdate(shortVideo);

        //更新分类信息（视频标签）
        String videoCategoryId = videoSaveDTO.getShortVideoCategoryId();
        if (StringUtils.isNotEmpty(videoCategoryId)) {

            //先删除视频和标签的绑定关系
            LambdaQueryWrapper<H2ShortVideoTag> updateWrapper = new LambdaQueryWrapper<>();
            updateWrapper.eq(H2ShortVideoTag::getVideoId, Long.valueOf(shortVideo.getId()));
            h2ShortVideoTagMapper.delete(updateWrapper);

            //从新保存标签绑定关系
            String[] split = videoCategoryId.split(",");
            for (String id : split) {
                H2ShortVideoCategory category = videoCategoryService.getById(id);
                if (null == category) {
                    throw new QysException("No short video classification information is obtained");
                }
                H2ShortVideoTag shortVideoTag = new H2ShortVideoTag();
                shortVideoTag.setVideoId(Long.valueOf(shortVideo.getId()));
                shortVideoTag.setTagCode(Long.valueOf(id));
                h2ShortVideoTagMapper.insert(shortVideoTag);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveVideoByApp(AppShortVideoSaveDTO shortVideoSaveDTO) {
        log.info("用户上传短视频信息: {},--->{}", SecurityUtils.getUsername(), shortVideoSaveDTO);

        H2ShortVideo shortVideo = new H2ShortVideo();
        BeanUtils.copyProperties(shortVideoSaveDTO, shortVideo);
        shortVideo.setStatus(0);
        shortVideo.setCreateTime(LocalDateTime.now());
        shortVideo.setDeleted(false);
//        shortVideo.setShortVideoCategoryId(shortVideoSaveDTO.getCategoryIds());

        //用户信息
        H2AppUser h2AppUser = appUserMapper.selectById(SecurityUtils.getUserId());
        if (null == h2AppUser) {
            throw new QysException(MessageUtils.message("user.null"));
        }
        AppUserLevel appUserLevel = appUserLevelMapper.selectById(h2AppUser.getUserLevelId());
        if (null == appUserLevel) {
//         用户等级信息异常
            throw new QysException(MessageUtils.message("level.info.error"));
        }
        if (1 != appUserLevel.getUpShortVideoFlag()) {
//         没有上传视频权限
            throw new QysException(MessageUtils.message("upload.video.power_error"));
        }
        shortVideo.setUserId(Long.valueOf(h2AppUser.getId()));
        shortVideo.setAvatar(h2AppUser.getAvatar());
        shortVideo.setUserName(h2AppUser.getNickName());

        //封面图片
//        shortVideo.setImg(getImg(shortVideo.getUrl()));
        shortVideo.setImg(shortVideo.getUrl());

        save(shortVideo);

        //更新分类信息（视频标签）
        String videoCategoryId = shortVideoSaveDTO.getCategoryIds();
        if (StringUtils.isNotEmpty(videoCategoryId)) {

            //先删除视频和标签的绑定关系
            LambdaQueryWrapper<H2ShortVideoTag> updateWrapper = new LambdaQueryWrapper<>();
            updateWrapper.eq(H2ShortVideoTag::getVideoId, Long.valueOf(shortVideo.getId()));
            h2ShortVideoTagMapper.delete(updateWrapper);

            //从新保存标签绑定关系
            String[] split = videoCategoryId.split(",");
            for (String id : split) {
                H2ShortVideoCategory category = videoCategoryService.getById(id);
                if (null == category) {
                    throw new QysException("No short video classification information is obtained");
                }
                H2ShortVideoTag shortVideoTag = new H2ShortVideoTag();
                shortVideoTag.setVideoId(Long.valueOf(shortVideo.getId()));
                shortVideoTag.setTagCode(Long.valueOf(id));
                h2ShortVideoTagMapper.insert(shortVideoTag);
            }
        }


        Long shopId = shopBaseMapper.queryShopBaseIdByUserId(SecurityUtils.getUserId());
        //绑定商品
        if(shopId != null && !CollectionUtils.isEmpty(shortVideoSaveDTO.getShopGoodsInfoId())){
            for (Long goodsInfoId : shortVideoSaveDTO.getShopGoodsInfoId()) {
                ShortVideoGoodsInfo shortVideoGoodsInfo = new ShortVideoGoodsInfo();
                shortVideoGoodsInfo.setVideoId(Long.valueOf(shortVideo.getId()));
                shortVideoGoodsInfo.setShopGoodsInfoId(goodsInfoId);
                shortVideoGoodsInfoMapper.insert(shortVideoGoodsInfo);
            }
        }
        if (CollectionUtils.isEmpty(shortVideoSaveDTO.getKeywords())){
            return;
        }
    }

    /**
     * 根据短视频连接获取封面图片
     *
     * @param url 短视频连接
     */
    private String getImg(String url) {
        VideoStore videoStore = videoStoreService.getOne(Wrappers.<VideoStore>query().eq("url", url));
        if (null != videoStore) {
            return videoStore.getImgUrl();
        }
        return null;
    }

    @Override
    public AppShortVideoVO getShortVideoByApp() {
        H2ShortVideo video;
        long count = 1;
        while (true) {
            //删除缓存还是没有视频则报错
            if (count > 10) {
                return null;
            }

            //获取视频信息
            H2ShortVideo shortVideo = this.getVideoByUserPreference(SecurityUtils.getUserId());
            if (null == shortVideo) {
                if (null==SecurityUtils.getUserId()){
                    video = baseMapper.randomOneVideo(null);
                }else {
                    video = baseMapper.randomOneVideo(SecurityUtils.getUserId());
                }

            } else {
                log.info("getVideoByUserPreference success");
                video = shortVideo;
            }

            //获取不到视频将缓存数据全部删除
            if (count == 5 || null == video) {
                count++;
                redisTemplate.delete(CacheConstants.APP_USER_SHORT_VIDEO);
                continue;
            }

            //校验视频是否被看过
            Boolean member = redisTemplate.opsForSet().isMember(CacheConstants.APP_USER_SHORT_VIDEO, video.getId());
            if (Boolean.FALSE.equals(member)) {
                redisTemplate.opsForSet().add(CacheConstants.APP_USER_SHORT_VIDEO, video.getId());

                //返回数据
                AppShortVideoVO vo = new AppShortVideoVO();
                BeanUtils.copyProperties(video, vo);
                //判断是否是直播
                if(vo.getUrl().startsWith(LiveStreamUtils.AGREEMENT)){
                    vo.setType(1);
                }

                //校验当前用户是否点赞/收藏该视频
                checkCurrentUserLikeOrCollection(vo);

                //是否关注用户
                count = userConcernService.checkUserConcern(SecurityUtils.getUserId(), vo.getUserId());
                vo.setConcern(count);

                //评论条数
                count = videoCommentsService.count(Wrappers.<H2ShortVideoComments>query().eq("`status`", 0)
                        .eq("short_video_id", vo.getId()));
                vo.setComments(count);

                //更新查看次数
                addVideoWatchCount(video.getId());

                //当前用户是否在直播中
                vo.setLiveing(isLiveing(vo.getUserId()));

                //是否绑定商品
                Long selectedCount = shortVideoGoodsInfoMapper.selectCount(Wrappers.<ShortVideoGoodsInfo>lambdaQuery().eq(ShortVideoGoodsInfo::getVideoId, video.getId()));
                vo.setBoundGoods(selectedCount == 0 ? Boolean.FALSE : Boolean.TRUE);

                //用户头像
                H2AppUser appUser = appUserMapper.selectById(vo.getUserId());
                vo.setAvatar(appUser == null ? null : appUser.getAvatar());
                return vo;
            }
            count++;
        }
    }

    private boolean isLiveing(Long userId) {
        AnchorLivesRoom room = anchorLivesRoomService.getRoomByUserId(userId);
        if (room != null) {
            return room.getLiveStatus() == 2;
        }
        return false;
    }


    private H2ShortVideo getVideoByUserPreference(Long userId) {

        //web端不支持刷到直播
        HttpServletRequest httpServletRequest = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String header = httpServletRequest.getHeader("User-Agent");
        if (StringUtils.isEmpty(header) || !header.startsWith("Mozilla")) {
            //随机获取直播(1/5概率)
            int i = new Random().nextInt(5);
            if(i == 0){
                Map<String, String> lives = getLives();
                if(!CollectionUtils.isEmpty(lives)){
                    H2ShortVideo h2ShortVideo = new H2ShortVideo();
                    h2ShortVideo.setTitle(lives.get("name"));
                    h2ShortVideo.setUrl(lives.get("url"));
                    h2ShortVideo.setUserId(Long.valueOf(lives.get("userId")));
                    h2ShortVideo.setId(lives.get("sessionId"));
                    h2ShortVideo.setUserName(lives.get("nikeName"));
                    h2ShortVideo.setAvatar(lives.get("avatar"));
                    return h2ShortVideo;
                }
            }
        }

        //获取近100条浏览记录中的偏好视频id
        LambdaQueryWrapper<ShortVideoHistory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShortVideoHistory::getUserId, userId);
        queryWrapper.eq(ShortVideoHistory::getFollow, 1);
        queryWrapper.last("limit 100");
        List<ShortVideoHistory> histories = videoHistoryService.list(queryWrapper);
        if (CollectionUtils.isEmpty(histories)) {
            return null;
        }
        List<Long> videoIds = histories.stream().map(ShortVideoHistory::getVideoId).toList();


        //获取100条偏好数据的所有标签
        LambdaQueryWrapper<H2ShortVideoTag> videoTaQueryWrapper = new LambdaQueryWrapper<>();
        videoTaQueryWrapper.in(H2ShortVideoTag::getVideoId, videoIds);

        List<H2ShortVideoTag> h2ShortVideoTags = h2ShortVideoTagMapper.selectList(videoTaQueryWrapper);
        if (CollectionUtils.isEmpty(h2ShortVideoTags)) {
            return null;
        }
        List<Long> codeList = h2ShortVideoTags.stream().map(H2ShortVideoTag::getTagCode).toList();

        //随机取标签
        Long tag = codeList.get(new Random().nextInt(codeList.size()));

        //根据标签随机获取视频
        LambdaQueryWrapper<H2ShortVideoTag> videoTagWrapper = new LambdaQueryWrapper<>();
        videoTagWrapper.eq(H2ShortVideoTag::getTagCode, tag);
        videoTagWrapper.notIn(H2ShortVideoTag::getVideoId,h2ShortVideoTags.stream().map(H2ShortVideoTag::getVideoId).collect(Collectors.toList()));
        List<H2ShortVideoTag> tagList = h2ShortVideoTagMapper.selectList(videoTagWrapper);
        if (CollectionUtils.isEmpty(tagList)) {
            return null;
        }

        //今日已观看视频
        List<Long> read = videoHistoryService.watchTodayCollection(userId);

        //随机取视频
        H2ShortVideoTag video = tagList.get(new Random().nextInt(tagList.size()));
        LambdaQueryWrapper<H2ShortVideo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(H2ShortVideo::getId, video.getVideoId()).ne(H2ShortVideo::getUserId, userId).notIn(!CollectionUtils.isEmpty(read), H2ShortVideo::getId, read);
        return h2ShortVideoMapper.selectOne(lambdaQueryWrapper);
    }


    private Map<String, String> getLives(){

        HashMap<String, String> map = Maps.newHashMap();

        AnchorLivesSession sessionServiceOne = anchorLivesSessionService.getOne(Wrappers.<AnchorLivesSession>lambdaQuery().eq(AnchorLivesSession::getLivesStatus, 2).last("ORDER BY RAND()").last("limit 1"));
        if(sessionServiceOne == null){
            return null;
        }
        //直播间名称
        String livesSessionName = sessionServiceOne.getLivesSessionName();
        //拉流地址
        H2AppUser user = anchorLivesRoomService.getUserByAnchorId(sessionServiceOne.getAnchorId());
        String url = LiveStreamUtils.getPlayUrl(Long.valueOf(user.getId()));

        map.put("name", livesSessionName);
        map.put("url", url);
        map.put("userId", user.getId());
        map.put("sessionId", String.valueOf(sessionServiceOne.getId()));
        map.put("nikeName", user.getNickName());
        map.put("avatar", user.getAvatar());

        return map;
    }

    /**
     * 短视频查看次数加一
     *
     * @param videoId 短视频id
     */
    private void addVideoWatchCount(String videoId) {
        ShortVideoEventDTO dto = new ShortVideoEventDTO();
        dto.setId(videoId);
        dto.setEventTypeEnum(ShortVideoEventTypeEnum.WATCH);
        dto.setUserId(SecurityUtils.getUserId());
        applicationContext.publishEvent(new ShortVideoAddEvent(dto));
    }

    /**
     * 校验当前用户是否点赞收藏该视频
     *
     * @param vo
     * @return
     */
    private void checkCurrentUserLikeOrCollection(AppShortVideoVO vo) {
        ShortVideoUser videoUser = shortVideoUserService.getOne(Wrappers.<ShortVideoUser>query()
                .eq("user_id", SecurityUtils.getUserId())
                .eq("video_id", vo.getId()));

        if (null != videoUser) {
            vo.setCurrentLike(Integer.valueOf(videoUser.getLike()));
            vo.setCurrentCollection(Integer.valueOf(videoUser.getCollection()));
        }
    }

    @Override
    public void forwardVideo(String videoId) {
        //修转发次数

        ShortVideoEventDTO dto = new ShortVideoEventDTO();
        dto.setId(videoId);
        dto.setEventTypeEnum(ShortVideoEventTypeEnum.FORWARD);
        ShortVideoAddEvent addEvent=new ShortVideoAddEvent(dto);
        applicationContext.publishEvent(addEvent);
    }

    /**
     * 用户点赞/查看/收藏/转发次数修改
     *
     * @param eventDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void incrementVideo(ShortVideoEventDTO eventDTO) {
        AtomicInteger count = new AtomicInteger(0);
        boolean lock = false;

        try {
            while (!lock) {

                lock = redisCache.getLock(CacheConstants.APP_SHORT_VIDEO, "11", 10, TimeUnit.SECONDS);
                if (!lock) {
                    int i = count.addAndGet(1);
                    if (i >= 10) {
                        log.info("获取锁信息失败");
                        return;
                    }
                }

                H2ShortVideo video = baseMapper.selectById(eventDTO.getId());
                if (null == video) return;

                switch (eventDTO.getEventTypeEnum()) {
                    case LIKE -> video.setLikeCount(video.getLikeCount() + eventDTO.getCount());
                    case COLLECTION -> video.setCollection(video.getCollection() + eventDTO.getCount());
                    case FORWARD -> video.setForward(video.getForward() + eventDTO.getCount());
                    case WATCH -> {
                        video.setWatch(video.getWatch() + eventDTO.getCount());
                        videoHistoryService.save(video, eventDTO.getUserId());
                    }
                }

                baseMapper.updateById(video);
            }
        } finally {
            if (lock) {
                redisTemplate.delete(CacheConstants.APP_SHORT_VIDEO);
            }
        }
    }

    /**
     * 根据id查询短视频信息
     *
     * @param id      短视频id
     * @param history 是否从浏览历史记录跳转
     */
    @Override
    public AppShortVideoVO getShortVideoById(Long id, Byte history) {
        H2ShortVideo shortVideo = baseMapper.selectById(id);
        if (null == shortVideo) {
            throw new QysException(MessageUtils.message("video.not.found"));
        }

        //返回数据
        AppShortVideoVO vo = new AppShortVideoVO();
        BeanUtils.copyProperties(shortVideo, vo);

        //校验当前用户是否点赞收藏该视频
        checkCurrentUserLikeOrCollection(vo);

        //是否关注用户
        Integer concern = userConcernService.checkUserConcern(SecurityUtils.getUserId(), vo.getUserId());
        vo.setConcern(Long.valueOf(concern));

        //评论条数
        Long count = videoCommentsService.count(Wrappers.<H2ShortVideoComments>query().eq("`status`", 0)
                .eq("short_video_id", vo.getId()));
        vo.setComments(count);

        //浏览历史记录跳转短视频查看次数加一
        if (null != history) {
            addVideoWatchCount(String.valueOf(id));
        }

        //是否绑定商品
        Long selectedCount = shortVideoGoodsInfoMapper.selectCount(Wrappers.<ShortVideoGoodsInfo>lambdaQuery().eq(ShortVideoGoodsInfo::getVideoId, shortVideo.getId()));
        vo.setBoundGoods(selectedCount == 0 ? Boolean.FALSE : Boolean.TRUE);
        return vo;
    }

    /**
     * 用发布短视频查询
     *
     * @param baseQuery {@link  BaseQuery}
     */
    @Override
    public Page<AppShortVideoVO> pageByApp(BaseQuery baseQuery) {
        Page<AppShortVideoVO> page = new Page<>(baseQuery.getPageNum(), baseQuery.getPageSize());
        page.setRecords(baseMapper.listShortVideoByApp(page, baseQuery));
        return page;
    }

    @Override
    public  AppShortVideoVO getFollowUserShortVideo() {
        AtomicInteger count = new AtomicInteger(0);
        boolean lock =false;
        try {
            while (true) {
                lock = redisCache.getLock(CacheConstants.APP_USER_CONCERN_SHORT_VIDEO_CRON+SecurityUtils.getUserId(), "11", 10, TimeUnit.SECONDS);
                if (lock) {
                    return getFollowUserShortVideoInfo();
                }
                int i = count.addAndGet(1);
                Thread.sleep(500);
                if (i >= 20) {
                    log.info("获取锁信息失败");
                    return null;
                }
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            if (lock) {
                redisTemplate.delete(CacheConstants.APP_USER_CONCERN_SHORT_VIDEO_CRON+SecurityUtils.getUserId());
            }
        }
    }

    public  AppShortVideoVO getFollowUserShortVideoInfo() {
        H2ShortVideo video;
        long count = 1;
        while (true) {
            //删除缓存还是没有视频则报错
            if (count > 10) {
                return null;
            }
            List<AppUserConcern> appUserConcerns=userConcernService.getUserConcerns(SecurityUtils.getUserId());
            if (CollectionUtils.isEmpty(appUserConcerns)){
                return null;
            }
            List<Long> userids =appUserConcerns.stream().map(AppUserConcern::getConcernId).collect(Collectors.toList());
            //获取视频信息
            video = baseMapper.randomOneVideos(userids);
            //获取不到视频将缓存数据全部删除
            if (count == 5 || null == video) {
                count++;
                redisTemplate.delete(CacheConstants.APP_USER_CONCERN_SHORT_VIDEO);
                continue;
            }

            //校验视频是否被看过
            Boolean member = redisTemplate.opsForSet().isMember(CacheConstants.APP_USER_CONCERN_SHORT_VIDEO, video.getId());
            if (Boolean.FALSE.equals(member)) {
                redisTemplate.opsForSet().add(CacheConstants.APP_USER_CONCERN_SHORT_VIDEO, video.getId());

                //返回数据
                AppShortVideoVO vo = new AppShortVideoVO();
                BeanUtils.copyProperties(video, vo);

                //校验当前用户是否点赞/收藏该视频
                checkCurrentUserLikeOrCollection(vo);

                //是否关注用户
                vo.setConcern(1L);

                //评论条数
                long countCom = videoCommentsService.count(Wrappers.<H2ShortVideoComments>query().eq("`status`", 0)
                        .eq("short_video_id", vo.getId()));
                vo.setComments(countCom);

                //更新查看次数
                addVideoWatchCount(video.getId());

                //当前用户是否在直播中
                vo.setLiveing(isLiveing(vo.getUserId()));

                //是否绑定商品
                Long selectedCount = shortVideoGoodsInfoMapper.selectCount(Wrappers.<ShortVideoGoodsInfo>lambdaQuery().eq(ShortVideoGoodsInfo::getVideoId, video.getId()));
                vo.setBoundGoods(selectedCount == 0 ? Boolean.FALSE : Boolean.TRUE);
                return vo;
            }
            count++;
        }
    }

    @Override
    public boolean hasShop(Long userId) {
        Long id = shopBaseMapper.queryShopBaseIdByUserId(userId);
        return id != null;
    }

    @Override
    public IPage<ShopGoodsInfo> getShopGoodsInfoByVideo(BaseQuery baseQuery) {
        List<ShortVideoGoodsInfo> videoGoodsInfos = shortVideoGoodsInfoMapper.selectList(Wrappers.<ShortVideoGoodsInfo>lambdaQuery().eq(ShortVideoGoodsInfo::getVideoId, baseQuery.getId()));
        if(!CollectionUtils.isEmpty(videoGoodsInfos)){
            List<Long> shopGoodsInfoId = videoGoodsInfos.stream().map(ShortVideoGoodsInfo::getShopGoodsInfoId).toList();
            return shopGoodsInfoMapper.selectPage(new Page<>(baseQuery.getPageNum(), baseQuery.getPageSize()), Wrappers.<ShopGoodsInfo>lambdaQuery().in(ShopGoodsInfo::getId, shopGoodsInfoId).eq(ShopGoodsInfo::isStatus, 1));
        }
        return new Page<>(baseQuery.getPageNum(), baseQuery.getPageSize());
    }

    @Override
    public List<QuerykeywordsVO> querykeywords(String keywords) {
        List<QuerykeywordsVO> list=baseMapper.querykeywords(keywords);
        return list;
    }

    @Override
    public Page<AppUserCollectionLikeVO> recommendedPage(AppShortVideoPageDTO queryDTO) {
        Page<AppUserCollectionLikeVO> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        page=baseMapper.recommendedPage(page,queryDTO);
        return page;
    }

    @Override
    public IPage<LikedVideoVO> queryTheListOfLikedVideos(AppBaseDTO dto) {
        dto.setId(String.valueOf(SecurityUtils.getUserId()));
        Page<LikedVideoVO> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        page.setRecords(baseMapper.getLikedVideos(page, dto));
        return page;
    }

    @Override
    public IPage<CommentVideoVO> queryTheListOfCommentVideos(AppBaseDTO dto) {
        dto.setId(String.valueOf(SecurityUtils.getUserId()));
        Page<CommentVideoVO> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        page.setRecords(baseMapper.getCommentVideos(page, dto));
        return page;
    }

    @Override
    public IPage<CommentVideoVO> viewCommentsBasedOnVideoId(Long videoId, AppBaseDTO dto) {
        dto.setId(String.valueOf(videoId));
        Page<CommentVideoVO> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        List<CommentVideoVO> commentList = baseMapper.getCommentsBasedOnVideoId(page, dto);
        for (CommentVideoVO comment : commentList) {
            List<CommentVideoVO> childComment = baseMapper.getCommentByParentId(comment.getCommentId(), SecurityUtils.getUserId());
            comment.setChildComment(childComment);
        }
        page.setRecords(commentList);
        return page;
    }
}
